import exifr from 'exifr';
import fs from 'fs/promises';

/**
 * 图片元数据接口
 */
export interface ImageMetadata {
  // 基础信息
  width?: number;
  height?: number;
  orientation?: number;
  colorSpace?: string;
  
  // 拍摄信息
  make?: string;              // 相机制造商
  model?: string;             // 相机型号
  software?: string;          // 软件信息
  
  // 镜头信息
  lensModel?: string;         // 镜头型号
  lensMake?: string;          // 镜头制造商
  focalLength?: number;       // 焦距
  focalLengthIn35mm?: number; // 35mm 等效焦距
  
  // 曝光参数
  aperture?: number;          // 光圈值 (f-number)
  shutterSpeed?: number;      // 快门速度（秒）
  shutterSpeedString?: string; // 快门速度字符串表示
  iso?: number;               // ISO 感光度
  exposureMode?: string;      // 曝光模式
  exposureProgram?: string;   // 曝光程序
  exposureBias?: number;      // 曝光补偿
  meteringMode?: string;      // 测光模式
  
  // 闪光灯
  flash?: boolean;            // 是否使用闪光灯
  flashMode?: string;         // 闪光灯模式
  
  // 白平衡和色彩
  whiteBalance?: string;      // 白平衡
  colorTemperature?: number;  // 色温
  saturation?: string;        // 饱和度
  sharpness?: string;         // 锐度
  contrast?: string;          // 对比度
  
  // 时间信息
  dateTime?: Date;            // 拍摄时间
  dateTimeOriginal?: Date;    // 原始拍摄时间
  dateTimeDigitized?: Date;   // 数字化时间
  
  // GPS 信息
  latitude?: number;          // 纬度
  longitude?: number;         // 经度
  altitude?: number;          // 海拔
  gpsDirection?: number;      // GPS 方向
  gpsSpeed?: number;          // GPS 速度
  
  // 其他信息
  copyright?: string;         // 版权信息
  artist?: string;            // 艺术家/摄影师
  description?: string;       // 描述
  keywords?: string[];        // 关键词
  rating?: number;            // 评分
  
  // 技术信息
  compression?: string;       // 压缩方式
  bitsPerSample?: number;     // 每样本位数
  photometricInterpretation?: string; // 光度解释
  
  // 原始数据（用于调试）
  raw?: any;
}

/**
 * 元数据提取选项
 */
export interface ExtractionOptions {
  includeRaw?: boolean;       // 是否包含原始 EXIF 数据
  parseGPS?: boolean;         // 是否解析 GPS 信息
  parseDates?: boolean;       // 是否解析日期
  includeKeywords?: boolean;  // 是否包含关键词
  timeout?: number;           // 超时时间（毫秒）
}

/**
 * 元数据提取器类
 */
export class MetadataExtractor {
  
  /**
   * 提取图片元数据
   */
  public async extractMetadata(
    imagePath: string,
    options: ExtractionOptions = {}
  ): Promise<ImageMetadata> {
    const {
      includeRaw = false,
      parseGPS = true,
      parseDates = true,
      includeKeywords = true,
      timeout = 10000
    } = options;

    console.log(`正在提取元数据: ${imagePath}`);

    try {
      // 检查文件是否存在
      await this.checkFileExists(imagePath);

      // 配置 exifr 选项
      const exifrOptions = {
        gps: parseGPS,
        exif: true,
        iptc: includeKeywords,
        xmp: includeKeywords,
        translateKeys: true,
        translateValues: true,
        reviveValues: true,
        sanitize: true,
        mergeOutput: true,
        silentErrors: false
      };

      // 提取原始 EXIF 数据
      const rawExif = await Promise.race([
        exifr.parse(imagePath, exifrOptions),
        new Promise((_, reject) => 
          setTimeout(() => reject(new Error('元数据提取超时')), timeout)
        )
      ]) as any;

      // 转换为标准化的元数据格式
      const metadata = this.normalizeMetadata(rawExif, parseDates);

      // 包含原始数据（如果需要）
      if (includeRaw) {
        metadata.raw = rawExif;
      }

      console.log(`元数据提取完成: ${imagePath}`);
      return metadata;

    } catch (error) {
      console.error(`提取元数据失败: ${imagePath}`, error);
      
      // 返回基础元数据（如果可能）
      try {
        const basicInfo = await this.extractBasicInfo(imagePath);
        return basicInfo;
      } catch (basicError) {
        console.error(`提取基础信息也失败: ${imagePath}`, basicError);
        throw error;
      }
    }
  }

  /**
   * 批量提取元数据
   */
  public async extractMetadataBatch(
    imagePaths: string[],
    options: ExtractionOptions = {},
    onProgress?: (current: number, total: number, currentPath: string) => void
  ): Promise<{ path: string; metadata: ImageMetadata | null; error?: string }[]> {
    console.log(`开始批量提取 ${imagePaths.length} 个文件的元数据`);

    const results: { path: string; metadata: ImageMetadata | null; error?: string }[] = [];

    for (let i = 0; i < imagePaths.length; i++) {
      const imagePath = imagePaths[i];
      
      try {
        // 调用进度回调
        if (onProgress) {
          onProgress(i + 1, imagePaths.length, imagePath);
        }

        const metadata = await this.extractMetadata(imagePath, options);
        results.push({ path: imagePath, metadata });

      } catch (error) {
        console.error(`批量提取元数据失败: ${imagePath}`, error);
        results.push({
          path: imagePath,
          metadata: null,
          error: error instanceof Error ? error.message : String(error)
        });
      }
    }

    console.log(`批量元数据提取完成: 成功 ${results.filter(r => r.metadata).length}，失败 ${results.filter(r => r.error).length}`);
    return results;
  }

  /**
   * 标准化元数据
   */
  private normalizeMetadata(rawExif: any, parseDates: boolean): ImageMetadata {
    const metadata: ImageMetadata = {};

    if (!rawExif) return metadata;

    try {
      // 基础信息
      metadata.width = rawExif.ExifImageWidth || rawExif.ImageWidth || rawExif.PixelXDimension;
      metadata.height = rawExif.ExifImageHeight || rawExif.ImageHeight || rawExif.PixelYDimension;
      metadata.orientation = rawExif.Orientation;
      metadata.colorSpace = rawExif.ColorSpace;

      // 相机信息
      metadata.make = rawExif.Make;
      metadata.model = rawExif.Model;
      metadata.software = rawExif.Software;

      // 镜头信息
      metadata.lensModel = rawExif.LensModel;
      metadata.lensMake = rawExif.LensMake;
      metadata.focalLength = rawExif.FocalLength;
      metadata.focalLengthIn35mm = rawExif.FocalLengthIn35mmFilm;

      // 曝光参数
      metadata.aperture = rawExif.FNumber || rawExif.ApertureValue;
      metadata.shutterSpeed = rawExif.ExposureTime || rawExif.ShutterSpeedValue;
      metadata.shutterSpeedString = this.formatShutterSpeed(metadata.shutterSpeed);
      metadata.iso = rawExif.ISO || rawExif.ISOSpeedRatings;
      metadata.exposureMode = rawExif.ExposureMode;
      metadata.exposureProgram = rawExif.ExposureProgram;
      metadata.exposureBias = rawExif.ExposureBiasValue;
      metadata.meteringMode = rawExif.MeteringMode;

      // 闪光灯
      metadata.flash = rawExif.Flash !== undefined ? Boolean(rawExif.Flash & 1) : undefined;
      metadata.flashMode = rawExif.FlashMode;

      // 白平衡和色彩
      metadata.whiteBalance = rawExif.WhiteBalance;
      metadata.colorTemperature = rawExif.ColorTemperature;
      metadata.saturation = rawExif.Saturation;
      metadata.sharpness = rawExif.Sharpness;
      metadata.contrast = rawExif.Contrast;

      // 时间信息
      if (parseDates) {
        metadata.dateTime = this.parseDate(rawExif.DateTime);
        metadata.dateTimeOriginal = this.parseDate(rawExif.DateTimeOriginal);
        metadata.dateTimeDigitized = this.parseDate(rawExif.DateTimeDigitized);
      }

      // GPS 信息
      if (rawExif.latitude !== undefined && rawExif.longitude !== undefined) {
        metadata.latitude = rawExif.latitude;
        metadata.longitude = rawExif.longitude;
        metadata.altitude = rawExif.altitude;
        metadata.gpsDirection = rawExif.GPSImgDirection;
        metadata.gpsSpeed = rawExif.GPSSpeed;
      }

      // 其他信息
      metadata.copyright = rawExif.Copyright;
      metadata.artist = rawExif.Artist;
      metadata.description = rawExif.ImageDescription || rawExif.Description;
      metadata.keywords = this.extractKeywords(rawExif);
      metadata.rating = rawExif.Rating;

      // 技术信息
      metadata.compression = rawExif.Compression;
      metadata.bitsPerSample = rawExif.BitsPerSample;
      metadata.photometricInterpretation = rawExif.PhotometricInterpretation;

    } catch (error) {
      console.error('标准化元数据时出错:', error);
    }

    return metadata;
  }

  /**
   * 提取基础信息（当 EXIF 提取失败时的备选方案）
   */
  private async extractBasicInfo(imagePath: string): Promise<ImageMetadata> {
    try {
      // 尝试使用 exifr 的基础功能
      const basicInfo = await exifr.parse(imagePath, {
        gps: false,
        exif: false,
        iptc: false,
        xmp: false,
        translateKeys: false,
        translateValues: false,
        reviveValues: false,
        sanitize: true,
        mergeOutput: false
      });

      return {
        width: basicInfo?.ImageWidth || basicInfo?.ExifImageWidth,
        height: basicInfo?.ImageHeight || basicInfo?.ExifImageHeight,
        orientation: basicInfo?.Orientation,
        make: basicInfo?.Make,
        model: basicInfo?.Model
      };
    } catch (error) {
      console.error('提取基础信息失败:', error);
      return {};
    }
  }

  /**
   * 检查文件是否存在
   */
  private async checkFileExists(filePath: string): Promise<void> {
    try {
      await fs.access(filePath);
    } catch (error) {
      throw new Error(`文件不存在: ${filePath}`);
    }
  }

  /**
   * 解析日期字符串
   */
  private parseDate(dateString: string | Date | undefined): Date | undefined {
    if (!dateString) return undefined;
    
    if (dateString instanceof Date) {
      return dateString;
    }

    try {
      // EXIF 日期格式通常是 "YYYY:MM:DD HH:mm:ss"
      // 先替换前两个冒号为短横线，然后将短横线替换回冒号（只替换前两个）
      let normalizedDate = dateString;
      normalizedDate = normalizedDate.replace(':', '-');
      normalizedDate = normalizedDate.replace(':', '-');
      const date = new Date(normalizedDate);
      
      return isNaN(date.getTime()) ? undefined : date;
    } catch (error) {
      console.warn('解析日期失败:', dateString, error);
      return undefined;
    }
  }

  /**
   * 格式化快门速度
   */
  private formatShutterSpeed(speed: number | undefined): string | undefined {
    if (speed === undefined) return undefined;

    if (speed >= 1) {
      return `${speed}s`;
    } else if (speed > 0) {
      const fraction = Math.round(1 / speed);
      return `1/${fraction}s`;
    }

    return undefined;
  }

  /**
   * 提取关键词
   */
  private extractKeywords(rawExif: any): string[] | undefined {
    const keywords: string[] = [];

    try {
      // 从不同字段提取关键词
      if (rawExif.Keywords) {
        if (Array.isArray(rawExif.Keywords)) {
          keywords.push(...rawExif.Keywords);
        } else if (typeof rawExif.Keywords === 'string') {
          keywords.push(...rawExif.Keywords.split(/[,;]/));
        }
      }

      if (rawExif.Subject) {
        if (Array.isArray(rawExif.Subject)) {
          keywords.push(...rawExif.Subject);
        } else if (typeof rawExif.Subject === 'string') {
          keywords.push(...rawExif.Subject.split(/[,;]/));
        }
      }

      // 清理和去重
      const cleanedKeywords = keywords
        .map(k => k.trim())
        .filter(k => k.length > 0)
        .filter((k, i, arr) => arr.indexOf(k) === i);

      return cleanedKeywords.length > 0 ? cleanedKeywords : undefined;
    } catch (error) {
      console.warn('提取关键词失败:', error);
      return undefined;
    }
  }

  /**
   * 获取支持的文件格式
   */
  public static getSupportedFormats(): string[] {
    return [
      'jpg', 'jpeg', 'png', 'tiff', 'tif', 'webp',
      'heic', 'heif', 'raw', 'cr2', 'nef', 'arw', 'dng', 'orf'
    ];
  }

  /**
   * 检查文件是否支持元数据提取
   */
  public static isSupportedFile(filePath: string): boolean {
    const extension = filePath.split('.').pop()?.toLowerCase();
    return extension ? this.getSupportedFormats().includes(extension) : false;
  }
}